package com.beiding.my.common;

import org.hibernate.SessionFactory;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.metamodel.spi.MetamodelImplementor;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.SingleTableEntityPersister;
import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/*
    只涉及Be层
 */
@Component
class TypeTableMapperHelper implements InitializingBean {

    @Autowired
    private EntityManager entityManager;

    private Map<Class, TypeTableMapper> typeTableMapperMap = new HashMap<>();
    private Map<String, TypeTableMapper> stringTypeTableMapperMap = new HashMap<>();

    @Override
    public void afterPropertiesSet() throws Exception {
        EntityManagerFactory beanEntityManagerFactory = entityManager.getEntityManagerFactory();
        SessionFactoryImpl sessionFactory = (SessionFactoryImpl) beanEntityManagerFactory.unwrap(SessionFactory.class);
        MetamodelImplementor metamodelImplementor = sessionFactory.getMetamodel();

        for (EntityPersister value : metamodelImplementor.entityPersisters().values()) {
            Class aClass = value.getMappedClass();
            SingleTableEntityPersister entityPersister = (SingleTableEntityPersister) value;
            TypeTableMapper typeTableMapper = new TypeTableMapper();
            typeTableMapper.tableName = entityPersister.getTableName();
            Iterable<AttributeDefinition> attributes = entityPersister.getAttributes();
            Map<String, String> f2c = new HashMap<>();
            Map<String, String> c2f = new HashMap<>();
            Map<String, String> df2c = new HashMap<>();
            Map<String, String> dc2f = new HashMap<>();
            Set<String> fields = new HashSet<>();
            handle(entityPersister, attributes, f2c, c2f, df2c, dc2f, fields);
            typeTableMapper.fieldToTableColMap = f2c;
            typeTableMapper.tableColFieldMap = c2f;
            typeTableMapper.differentFieldToTableColMap = df2c;
            typeTableMapper.differentTableColFieldMap = dc2f;
            typeTableMapper.fields = fields;
            fields.add("id");
            c2f.put("id", "id");
            f2c.put("id", "id");
            typeTableMapper.type = aClass;
            typeTableMapper.entityName = aClass.getName();
            typeTableMapperMap.put(aClass, typeTableMapper);
            stringTypeTableMapperMap.put(aClass.getName(), typeTableMapper);
        }

    }

    TypeTableMapper getTypeTableMapperFromBo(Class<? extends Bo> c) {
        return typeTableMapperMap.get(BoVoBe.getBeTypeFromBoType(c));
    }


    TypeTableMapper getTypeTableMapper(Class c) {
        return typeTableMapperMap.get(c);
    }

    TypeTableMapper getTypeTableMapper(String c) {
        return stringTypeTableMapperMap.get(c);
    }

    private static void handle(SingleTableEntityPersister entityPersister, Iterable<AttributeDefinition> attributes, Map<String, String> f2c, Map<String, String> c2f, Map<String, String> df2c, Map<String, String> dc2f, Set<String> fields) {
        for (AttributeDefinition attr : attributes) {
            String propertyName = attr.getName(); //在entity中的属性名称
            fields.add(propertyName);
            String[] columnName = entityPersister.getPropertyColumnNames(propertyName); //对应数据库表中的字段名
            f2c.put(propertyName, columnName[0]);
            c2f.put(columnName[0], propertyName);
            if (!propertyName.equals(columnName[0])) {
                //有必要进行as映射的
                df2c.put(propertyName, columnName[0]);
                dc2f.put(columnName[0], propertyName);
            }
        }
    }


}
